/*     */ package com.zimbra.cs.account;
/*     */ 
/*     */ import com.google.common.base.Objects;
/*     */ import com.google.common.base.Objects.ToStringHelper;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.EmailUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.datasource.DataSourceManager;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.soap.admin.type.DataSourceType;
/*     */ import com.zimbra.soap.type.DataSource.ConnectionType;
/*     */ import java.io.PrintStream;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.security.GeneralSecurityException;
/*     */ import java.security.MessageDigest;
/*     */ import java.security.SecureRandom;
/*     */ import java.util.Arrays;
/*     */ import java.util.HashMap;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.UUID;
/*     */ import javax.crypto.Cipher;
/*     */ import javax.crypto.spec.SecretKeySpec;
/*     */ import org.apache.commons.codec.binary.Base64;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class DataSource
/*     */   extends AccountProperty
/*     */ {
/*     */   private static final int SALT_SIZE_BYTES = 16;
/*     */   private static final int AES_PAD_SIZE = 16;
/*  54 */   private static final byte[] VERSION = { 1 };
/*     */   
/*     */ 
/*     */ 
/*     */   public static final String CT_CLEARTEXT = "cleartext";
/*     */   
/*     */ 
/*     */ 
/*     */   public static final String CT_SSL = "ssl";
/*     */   
/*     */ 
/*     */   private DataSourceType mType;
/*     */   
/*     */ 
/*     */   protected DataSourceConfig.Service knownService;
/*     */   
/*     */ 
/*     */ 
/*     */   public DataSource(Account acct, DataSourceType type, String name, String id, Map<String, Object> attrs, Provisioning prov)
/*     */   {
/*  74 */     super(acct, name, id, attrs, null, prov);
/*  75 */     this.mType = type;
/*     */     
/*  77 */     initKnownService();
/*     */   }
/*     */   
/*     */   public Entry.EntryType getEntryType()
/*     */   {
/*  82 */     return Entry.EntryType.DATASOURCE;
/*     */   }
/*     */   
/*     */   private void initKnownService()
/*     */   {
/*  87 */     String host = getHost();
/*     */     String serviceName;
/*     */     String serviceName;
/*  90 */     if ((host != null) && ((host.endsWith(".gmail.com")) || (host.endsWith(".googlemail.com")))) {
/*  91 */       serviceName = "gmail.com";
/*     */     } else {
/*  93 */       serviceName = getDomain();
/*     */     }
/*  95 */     this.knownService = (serviceName == null ? null : DataSourceManager.getConfig().getService(serviceName));
/*     */   }
/*     */   
/*     */   public DataSourceType getType() {
/*  99 */     return this.mType;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public boolean isManaged()
/*     */   {
/* 110 */     return DataSourceManager.isManaged(this);
/*     */   }
/*     */   
/* 113 */   public boolean isEnabled() { return getBooleanAttr("zimbraDataSourceEnabled", false); }
/*     */   
/*     */   public DataSource.ConnectionType getConnectionType()
/*     */   {
/* 117 */     String value = getAttr("zimbraDataSourceConnectionType");
/* 118 */     if (value == null) {
/*     */       try
/*     */       {
/* 121 */         value = Provisioning.getInstance().getConfig().getDataSourceConnectionTypeAsString();
/*     */       }
/*     */       catch (ServiceException e) {}
/*     */     }
/*     */     
/* 126 */     if (value != null) {
/*     */       try {
/* 128 */         return DataSource.ConnectionType.valueOf(value);
/*     */       } catch (IllegalArgumentException e) {
/* 130 */         ZimbraLog.mailbox.warn("Illegal connection type: " + value);
/*     */       }
/*     */     }
/* 133 */     return DataSource.ConnectionType.cleartext;
/*     */   }
/*     */   
/*     */   public boolean isSslEnabled() {
/* 137 */     return getConnectionType() == DataSource.ConnectionType.ssl;
/*     */   }
/*     */   
/* 140 */   public int getFolderId() { return getIntAttr("zimbraDataSourceFolderId", -1); }
/*     */   
/* 142 */   public String getHost() { return getAttr("zimbraDataSourceHost"); }
/*     */   
/* 144 */   public String getUsername() { return getAttr("zimbraDataSourceUsername"); }
/*     */   
/* 146 */   public String getAuthId() { return getAttr("zimbraDataSourceAuthorizationId"); }
/*     */   
/* 148 */   public String getAuthMechanism() { return getAttr("zimbraDataSourceAuthMechanism"); }
/*     */   
/*     */   public String getDomain() {
/* 151 */     String domain = getAttr("zimbraDataSourceDomain", null);
/* 152 */     if (domain == null) {
/* 153 */       domain = EmailUtil.getValidDomainPart(getEmailAddress());
/*     */     }
/* 155 */     return domain;
/*     */   }
/*     */   
/*     */   public Integer getPort() {
/* 159 */     if (getAttr("zimbraDataSourcePort") == null) {
/* 160 */       return null;
/*     */     }
/* 162 */     return Integer.valueOf(getIntAttr("zimbraDataSourcePort", -1));
/*     */   }
/*     */   
/*     */   public String getDecryptedPassword() throws ServiceException {
/* 166 */     String data = getAttr("zimbraDataSourcePassword");
/* 167 */     return data == null ? null : decryptData(getId(), data);
/*     */   }
/*     */   
/*     */   public Integer getConnectTimeout(int defaultValue) {
/* 171 */     return Integer.valueOf(getIntAttr("zimbraDataSourceConnectTimeout", defaultValue));
/*     */   }
/*     */   
/*     */   public int getReadTimeout(int defaultValue) {
/* 175 */     return getIntAttr("zimbraDataSourceReadTimeout", defaultValue);
/*     */   }
/*     */   
/*     */   public int getMaxTraceSize() {
/* 179 */     return getIntAttr("zimbraDataSourceMaxTraceSize", 64);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public long getPollingInterval()
/*     */     throws ServiceException
/*     */   {
/* 189 */     String val = getAttr("zimbraDataSourcePollingInterval");
/* 190 */     Provisioning prov = Provisioning.getInstance();
/* 191 */     Account account = getAccount();
/*     */     long interval;
/*     */     long interval;
/* 194 */     if (val != null) {
/* 195 */       interval = getTimeInterval("zimbraDataSourcePollingInterval", 0L);
/*     */     } else {
/* 197 */       migratePollingIntervalIfNecessary(prov, account);
/* 198 */       switch (getType()) {
/*     */       case pop3: 
/* 200 */         interval = account.getDataSourcePop3PollingInterval();
/* 201 */         break;
/*     */       case imap: 
/* 203 */         interval = account.getDataSourceImapPollingInterval();
/* 204 */         break;
/*     */       case rss: 
/* 206 */         interval = account.getDataSourceRssPollingInterval();
/* 207 */         break;
/*     */       case caldav: 
/* 209 */         interval = account.getDataSourceCaldavPollingInterval();
/* 210 */         break;
/*     */       case yab: 
/* 212 */         interval = account.getDataSourceYabPollingInterval();
/* 213 */         break;
/*     */       case cal: 
/* 215 */         interval = account.getDataSourceCalendarPollingInterval();
/* 216 */         break;
/*     */       case gal: 
/* 218 */         interval = account.getDataSourceGalPollingInterval();
/* 219 */         break;
/*     */       default: 
/* 221 */         return 0L;
/*     */       }
/*     */       
/*     */     }
/* 225 */     if (interval < 0L)
/*     */     {
/* 227 */       return 0L;
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 232 */     long min = account.getDataSourceMinPollingInterval();
/* 233 */     long safeguard = 10000L;
/* 234 */     if (min < safeguard) {
/* 235 */       min = safeguard;
/*     */     }
/* 237 */     if ((0L < interval) && (interval < min)) {
/* 238 */       interval = min;
/*     */     }
/*     */     
/* 241 */     return interval;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private void migratePollingIntervalIfNecessary(Provisioning prov, Account account)
/*     */     throws ServiceException
/*     */   {
/* 252 */     String oldInterval = account.getAttr("zimbraDataSourcePollingInterval", false);
/* 253 */     if (!StringUtil.isNullOrEmpty(oldInterval)) {
/* 254 */       ZimbraLog.datasource.info("Migrating account POP3 and IMAP polling intervals to %s.", new Object[] { oldInterval });
/* 255 */       Map<String, Object> attrs = new HashMap();
/* 256 */       attrs.put("zimbraDataSourcePollingInterval", "");
/* 257 */       attrs.put("zimbraDataSourcePop3PollingInterval", oldInterval);
/* 258 */       attrs.put("zimbraDataSourceImapPollingInterval", oldInterval);
/* 259 */       prov.modifyAttrs(account, attrs, true, false);
/*     */     }
/*     */     
/*     */ 
/* 263 */     Cos cos = account.getCOS();
/* 264 */     oldInterval = cos.getAttr("zimbraDataSourcePollingInterval", false);
/* 265 */     if (!StringUtil.isNullOrEmpty(oldInterval)) {
/* 266 */       ZimbraLog.datasource.info("Migrating COS POP3 and IMAP polling intervals to %s.", new Object[] { oldInterval });
/* 267 */       Map<String, Object> attrs = new HashMap();
/* 268 */       attrs.put("zimbraDataSourcePollingInterval", "");
/* 269 */       attrs.put("zimbraDataSourcePop3PollingInterval", oldInterval);
/* 270 */       attrs.put("zimbraDataSourceImapPollingInterval", oldInterval);
/* 271 */       prov.modifyAttrs(cos, attrs, true, false);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public boolean isScheduled()
/*     */     throws ServiceException
/*     */   {
/* 280 */     return getPollingInterval() > 0L;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public boolean leaveOnServer()
/*     */   {
/* 289 */     return getBooleanAttr("zimbraDataSourceLeaveOnServer", true);
/*     */   }
/*     */   
/*     */   public String getEmailAddress() {
/* 293 */     return getAttr("zimbraDataSourceEmailAddress");
/*     */   }
/*     */   
/*     */   public boolean useAddressForForwardReply() {
/* 297 */     return getBooleanAttr("zimbraDataSourceUseAddressForForwardReply", false);
/*     */   }
/*     */   
/*     */   public String getDefaultSignature() {
/* 301 */     return getAttr("zimbraPrefDefaultSignatureId");
/*     */   }
/*     */   
/*     */   public String getForwardReplySignature() {
/* 305 */     return getAttr("zimbraPrefForwardReplySignatureId");
/*     */   }
/*     */   
/*     */   public String getFromDisplay() {
/* 309 */     return getAttr("zimbraPrefFromDisplay");
/*     */   }
/*     */   
/*     */   public String getReplyToAddress() {
/* 313 */     return getAttr("zimbraPrefReplyToAddress");
/*     */   }
/*     */   
/*     */   public String getReplyToDisplay() {
/* 317 */     return getAttr("zimbraPrefReplyToDisplay");
/*     */   }
/*     */   
/* 320 */   boolean isRequestScopeDebugTraceOn = false;
/*     */   
/* 322 */   public synchronized void setRequestScopeDebugTraceOn(boolean b) { this.isRequestScopeDebugTraceOn = b; }
/*     */   
/*     */   public boolean isImportOnly()
/*     */   {
/* 326 */     return getBooleanAttr("zimbraDataSourceImportOnly", false);
/*     */   }
/*     */   
/*     */   public boolean isInternal() {
/* 330 */     return getBooleanAttr("zimbraDataSourceIsInternal", false);
/*     */   }
/*     */   
/*     */   public boolean isDebugTraceEnabled() {
/* 334 */     return (this.isRequestScopeDebugTraceOn) || (getBooleanAttr("zimbraDataSourceEnableTrace", false));
/*     */   }
/*     */   
/*     */ 
/*     */   protected DataSourceConfig.Folder getKnownFolderByRemotePath(String remotePath)
/*     */   {
/* 340 */     return this.knownService != null ? this.knownService.getFolderByRemotePath(remotePath) : null;
/*     */   }
/*     */   
/*     */   protected DataSourceConfig.Folder getKnownFolderByLocalPath(String localPath) {
/* 344 */     return this.knownService != null ? this.knownService.getFolderByLocalPath(localPath) : null;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public String mapRemoteToLocalPath(String remotePath)
/*     */   {
/* 354 */     DataSourceConfig.Folder kf = getKnownFolderByRemotePath(remotePath);
/* 355 */     return kf != null ? kf.getLocalPath() : null;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public String mapLocalToRemotePath(String localPath)
/*     */   {
/* 365 */     DataSourceConfig.Folder kf = getKnownFolderByLocalPath(localPath);
/* 366 */     return kf != null ? kf.getRemotePath() : null;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public boolean ignoreRemotePath(String remotePath)
/*     */   {
/* 373 */     DataSourceConfig.Folder kf = getKnownFolderByRemotePath(remotePath);
/* 374 */     if (kf != null) { return kf.isIgnore();
/*     */     }
/* 376 */     String localPath = "/" + remotePath;
/* 377 */     return getKnownFolderByLocalPath(localPath) != null;
/*     */   }
/*     */   
/*     */   public boolean isSyncInboxOnly() {
/* 381 */     return false;
/*     */   }
/*     */   
/*     */   public boolean isSyncEnabled(String localPath) {
/* 385 */     return true;
/*     */   }
/*     */   
/*     */   public boolean isSaveToSent()
/*     */   {
/* 390 */     return true;
/*     */   }
/*     */   
/*     */   public boolean isOffline() {
/* 394 */     return false;
/*     */   }
/*     */   
/*     */   public boolean checkPendingMessages()
/*     */     throws ServiceException
/*     */   {
/* 400 */     return false;
/*     */   }
/*     */   
/*     */   public long getSyncFrequency() {
/* 404 */     return 0L;
/*     */   }
/*     */   
/*     */ 
/*     */   public void reportError(int itemId, String error, Exception e) {}
/*     */   
/*     */   private static byte[] randomSalt()
/*     */   {
/* 412 */     SecureRandom random = new SecureRandom();
/* 413 */     byte[] pad = new byte[16];
/* 414 */     random.nextBytes(pad);
/* 415 */     return pad;
/*     */   }
/*     */   
/*     */   private static Cipher getCipher(String dataSourceId, byte[] salt, boolean encrypt) throws GeneralSecurityException, UnsupportedEncodingException {
/* 419 */     MessageDigest md5 = MessageDigest.getInstance("MD5");
/* 420 */     md5.update(salt);
/* 421 */     md5.update(dataSourceId.getBytes("utf-8"));
/* 422 */     byte[] key = md5.digest();
/* 423 */     SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
/*     */     
/* 425 */     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
/* 426 */     cipher.init(encrypt ? 1 : 2, skeySpec);
/* 427 */     return cipher;
/*     */   }
/*     */   
/*     */   public static String encryptData(String dataSourceId, String data) throws ServiceException {
/*     */     try {
/* 432 */       byte[] salt = randomSalt();
/* 433 */       Cipher cipher = getCipher(dataSourceId, salt, true);
/* 434 */       byte[] dataBytes = cipher.doFinal(data.getBytes("utf-8"));
/* 435 */       byte[] toEncode = new byte[VERSION.length + salt.length + dataBytes.length];
/* 436 */       System.arraycopy(VERSION, 0, toEncode, 0, VERSION.length);
/* 437 */       System.arraycopy(salt, 0, toEncode, VERSION.length, salt.length);
/* 438 */       System.arraycopy(dataBytes, 0, toEncode, VERSION.length + salt.length, dataBytes.length);
/* 439 */       return new String(Base64.encodeBase64(toEncode));
/*     */     } catch (UnsupportedEncodingException e) {
/* 441 */       throw ServiceException.FAILURE("caught unsupport encoding exception", e);
/*     */     } catch (GeneralSecurityException e) {
/* 443 */       throw ServiceException.FAILURE("caught security exception", e);
/*     */     }
/*     */   }
/*     */   
/*     */   public static String decryptData(String dataSourceId, String data) throws ServiceException {
/*     */     try {
/* 449 */       byte[] encoded = Base64.decodeBase64(data.getBytes());
/* 450 */       if (encoded.length < VERSION.length + 16 + 16)
/* 451 */         throw ServiceException.FAILURE("invalid encoded size: " + encoded.length, null);
/* 452 */       byte[] version = new byte[VERSION.length];
/* 453 */       byte[] salt = new byte[16];
/* 454 */       System.arraycopy(encoded, 0, version, 0, VERSION.length);
/* 455 */       if (!Arrays.equals(version, VERSION))
/* 456 */         throw ServiceException.FAILURE("unsupported version", null);
/* 457 */       System.arraycopy(encoded, VERSION.length, salt, 0, 16);
/* 458 */       Cipher cipher = getCipher(dataSourceId, salt, false);
/* 459 */       return new String(cipher.doFinal(encoded, VERSION.length + 16, encoded.length - 16 - VERSION.length), "utf-8");
/*     */     } catch (UnsupportedEncodingException e) {
/* 461 */       throw ServiceException.FAILURE("caught unsupport encoding exception", e);
/*     */     } catch (GeneralSecurityException e) {
/* 463 */       throw ServiceException.FAILURE("caught security exception", e);
/*     */     }
/*     */   }
/*     */   
/*     */   public boolean isSyncEnabled(Folder folder) {
/* 468 */     return DataSourceManager.getInstance().isSyncEnabled(this, folder);
/*     */   }
/*     */   
/*     */   public boolean isSyncCapable(Folder folder) {
/* 472 */     return DataSourceManager.getInstance().isSyncCapable(this, folder);
/*     */   }
/*     */   
/*     */   public boolean isSyncNeeded() throws ServiceException {
/* 476 */     return false;
/*     */   }
/*     */   
/*     */   public void mailboxDeleted() {}
/*     */   
/*     */   public Mailbox getMailbox() throws ServiceException {
/* 482 */     return DataSourceManager.getInstance().getMailbox(this);
/*     */   }
/*     */   
/*     */   public String toString()
/*     */   {
/* 487 */     return Objects.toStringHelper(this).add("id", getId()).add("type", getType()).add("enabled", isEnabled()).add("name", getName()).add("host", getHost()).add("port", getPort()).add("connectionType", getConnectionType()).add("username", getUsername()).add("folderId", getFolderId()).toString();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void main(String[] args)
/*     */     throws ServiceException
/*     */   {
/* 501 */     String dataSourceId = UUID.randomUUID().toString();
/* 502 */     String enc = encryptData(dataSourceId, "helloworld");
/* 503 */     System.out.println(enc);
/* 504 */     System.out.println(decryptData(dataSourceId, enc));
/*     */   }
/*     */   
/*     */   public static abstract interface DataImport
/*     */   {
/*     */     public abstract void test()
/*     */       throws ServiceException;
/*     */     
/*     */     public abstract void importData(List<Integer> paramList, boolean paramBoolean)
/*     */       throws ServiceException;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/account/DataSource.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */